package com.xunshi.hikangvision.sevice;

import com.xunshi.hikangvision.untils.PreverViewUntil;
import com.xunshi.hikangvision.vo.LoginVo;
import com.xunshi.hikangvision.vo.MyBlockingQueue;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint(value = "/manyws/{wsId}")
@Component
public class ManyWebSocket {

    /**
     * 存储WebSocket连接
     */
    private static ConcurrentHashMap<String, ManyWebSocket> webSocketMap = new ConcurrentHashMap<>();

    private Integer playID;

    @OnOpen
    public void onOpen(final Session session , @PathParam("wsId") String wsId) {
        String sessionId = session.getId();
        webSocketMap.put(sessionId, this);
        log.info("连接建立，当前连接：{}，sessionid：{}",wsId,sessionId);

        // TODO 查询数据库获得摄像头信息
        LoginVo loginVo = new LoginVo();
        loginVo.setIp("192.168.0.211");
        loginVo.setProt("8000");
        loginVo.setUserName("admin");
        loginVo.setPassword("Ll123456");
        loginVo.setChannel(wsId);
        loginVo.setSessionId(sessionId);

        // 登录
        loginVo = PreverViewUntil.loginOnly(loginVo);

        // 预览
        if ("1".equals(loginVo.getLoginStatus())) {
            LoginVo payLoginVo = PreverViewUntil.playView(loginVo);
            this.playID = payLoginVo.getLPlayID();
        }

        // 像前台推流
        if(MyBlockingQueue.bpMap.containsKey(sessionId)){
            if(null==MyBlockingQueue.findPlayIdByUserId(sessionId)) {
                System.out.println(String.format("警告:根据登录句柄%s,没有找到用户预览句柄",sessionId));
            }
            BlockingQueue blockingQueue = MyBlockingQueue.bpMap.get(sessionId);

            //这里按照逻辑来说这里绑定后就应该开启一个线层来干这个事情，查询了一下好像websocket就是多线程的直接干吧
            while (null!=session&&session.isOpen()&&null!=blockingQueue) {
                try {
                    byte[] esBytes = (byte[]) blockingQueue.take();
                    if(esBytes.length<1) {
                        System.out.println("取流失败，无内容");
                        continue;
                    }
                    ByteBuffer data = ByteBuffer.wrap(esBytes);
                    session.getBasicRemote().sendBinary(data);
                } catch (InterruptedException e) {
                    System.out.println("socket 数据发失败，错误信息为："+e.getMessage());
                    return;
                } catch (IOException e) {
                    System.out.println("socket 数据发失败，错误信息为："+e.getMessage());
                    return;
                }
            }
        }
    }

    @OnClose
    public void onClose(final Session session) {
        log.info("关闭连接，sessionid：{}",session.getId());

        String sessionId = session.getId();
        if (webSocketMap.containsKey(sessionId)) {
            webSocketMap.remove(webSocketMap);
        }

        // 停止预览
        boolean isStop = PreverViewUntil.stopPreview(this.playID);
        if (isStop) {
            log.info("停止预览成功");
        } else {
            log.info("停止预览失败");
        }

        // 没有连接则退出登录
        if (webSocketMap.size() == 0) {
            Set<Map.Entry<String, LoginVo>> entries = MyBlockingQueue.IPToUserMap.entrySet();
            for (Map.Entry<String, LoginVo> entry : entries) {
                boolean isLogout = PreverViewUntil.logoutOnly(entry.getValue().getLUserID());
                if (isLogout) {
                    log.info(entry.getKey()+"：退出登录成功");
                } else {
                    log.info(entry.getKey()+"：退出登录失败");
                }
            }
        }
    }

    @OnMessage
    public void onMessage(final String message, final Session session) {
        log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
    }

    @OnError
    public void onError(final Session session, final Throwable error) {
        log.info("socket[{}]发生错误,错误消息是:{}", session.getId(), error.getMessage());

        String sessionId = session.getId();
        if (webSocketMap.containsKey(sessionId)) {
            webSocketMap.remove(webSocketMap);
        }

        // 停止预览
        boolean isStop = PreverViewUntil.stopPreview(this.playID);
        if (isStop) {
            log.info("停止预览成功");
        } else {
            log.info("停止预览失败");
        }

        // 没有连接则退出登录
        if (webSocketMap.size() == 0) {
            Set<Map.Entry<String, LoginVo>> entries = MyBlockingQueue.IPToUserMap.entrySet();
            for (Map.Entry<String, LoginVo> entry : entries) {
                boolean isLogout = PreverViewUntil.logoutOnly(entry.getValue().getLUserID());
                if (isLogout) {
                    log.info(entry.getKey()+"：退出登录成功");
                } else {
                    log.info(entry.getKey()+"：退出登录失败");
                }
            }
        }
    }
}
